package com.vouov.util;

import com.google.appengine.repackaged.com.google.common.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.util.Random;

/**
 * AES 加密解密工具类，主要消除各个系统之间的加密差异
 * User: yuminglong
 * Date: 11-11-18
 * Time: 下午7:34
 * Version: 1.0.0
 */
public class AESUtils {

    /**
     * 加密
     *
     * @param message
     * @param password
     * @return
     * @throws Exception
     */
    public static String encrypt(String message, String password) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
        //md5摘要，转换为16进制字符串
        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
        String md5Text = StringUtils.byte2hex(messageDigest.digest(password.getBytes("UTF-8")));
        //md5前16位作为Encoded， 后16位作为IV
        SecretKeySpec secretKeySpec = new SecretKeySpec(md5Text.getBytes(), 0, 16, "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(md5Text.getBytes(), 16, 16);
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
        byte[] bytes = cipher.doFinal(padString(message).getBytes("UTF-8"));
        return Base64.encode(bytes);
    }

    /**
     * 解密
     *
     * @param cipherText
     * @param password
     * @return
     * @throws Exception
     */
    public static String decrypt(String cipherText, String password) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
        //md5摘要，转换为16进制字符串
        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
        String md5Text = StringUtils.byte2hex(messageDigest.digest(password.getBytes("UTF-8")));
        //md5前16位作为Encoded， 后16位作为IV
        SecretKeySpec secretKeySpec = new SecretKeySpec(md5Text.getBytes(), 0, 16, "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(md5Text.getBytes(), 16, 16);
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
        byte[] plainText = cipher.doFinal(Base64.decode(cipherText));
        return new String(unpadString(plainText), "UTF-8");
    }

    /**
     * 字符串的长度不足16的倍数时， 补\0
     *
     * @param text
     * @return
     * @throws java.io.UnsupportedEncodingException
     */
    private static String padString(String text) throws UnsupportedEncodingException {
        char paddingChar = '\0';
        int size = 16;
        StringBuilder sb = new StringBuilder(text);
        int x = text.getBytes("UTF-8").length % size;
        int padLength = size - x;
        if (x > 0) {
            for (int i = 0; i < padLength; i++) {
                sb.append(paddingChar);
            }
        }
        return sb.toString();
    }

    /**
     * 字符串的长度是16的倍数时， 去除补\0
     *
     * @param bytes
     * @return
     * @throws java.io.UnsupportedEncodingException
     */
    private static byte[] unpadString(byte[] bytes) throws UnsupportedEncodingException {
        char paddingChar = '\0';
        int size = 16;
        int x = bytes.length % size;
        int padLength = 0;
        if (x == 0) {
            //查找尾部的\0
            for (int i = bytes.length - 1; i >= 0; i--) {
                if (bytes[i] == paddingChar) {
                    padLength++;
                } else {
                    break;
                }
            }
        }
        byte[] unpadBytes = new byte[bytes.length - padLength];
        for (int i = 0; i < unpadBytes.length; i++) {
            unpadBytes[i] = bytes[i];
        }
        return unpadBytes;
    }


    public void testAES() throws Exception {
        String content = "Asiainfo-linkage 亚信联创科技";
        Random random = new Random();
        String password = String.valueOf(random.nextInt());
        String cipherText = encrypt(content, password);
        System.out.println(cipherText);
        String plainText = decrypt(cipherText, password);
        System.out.println(plainText);
    }


    public void testAESDecrypt() throws Exception {
       String password = "123456";
        String cipherText = "paZ20lc2Emi7H7gE8HZNEFt3QPAuJe4vZUebOBawZe8=";
        System.out.println(cipherText);
        String plainText = decrypt(cipherText, password);
        System.out.println(plainText);
        System.out.println(plainText.length());
    }


    public void testAESEncrypt() throws Exception {
        String content = "Asiainfo-linkage 亚信联创科技";
        Random random = new Random();
        String password = String.valueOf(random.nextInt());
        password = "123456";
        System.out.println(password);
        String cipherText = encrypt(content, password);
        System.out.println(cipherText);
    }
}
